package org.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zhipu.oapi.ClientV4;
import com.zhipu.oapi.Constants;
import com.zhipu.oapi.service.v4.model.*;
import io.reactivex.Flowable;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;
import org.example.aop.Valid;
import org.example.entity.RequestLog;
import org.example.entity.User;
import org.example.feign.FeignConnect;
import org.example.mapper.RequestLogMapper;
import org.example.openAi.AiUtil;
import org.example.service.RequestLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;


@RestController
@RequestMapping("/test")
public class TestServiceController {

    private static final ClientV4 client = new ClientV4
            .Builder("51ca0c08adf2f23443414b8dd87a6fc9.vGRzvdzXWC7iogco")
            .networkConfig(1000 * 20, 1000 * 20, 1000 * 20, 1000 * 20, TimeUnit.MILLISECONDS)
            .build();
    @Resource
    private FeignConnect feignConnect;
    @Resource
    private RequestLogMapper requestLogMapper;

    @GetMapping("/getTestService")
    @ResponseBody
    public User getTestService(){
        User user = new User("本人虎伥", "断崖大桥", 666);
        return user;

    }

    @PostMapping("/testDate")
    public void testDate(){
        Date date = new Date();
        String s = feignConnect.testDate(date);
        System.out.println("success : "+s);
    }

    @PostMapping("/testAi")
    public void testAi(@RequestParam("question") String question){
        String answer = AiUtil.invoke(question);
        System.out.println(answer);
    }

    @PostMapping("/testAi3")
    public void testAi3(@RequestParam("question") String question){
        AiUtil.sseInvoke(question);
    }

//    @Valid
    @GetMapping("/testAi2")
    public SseEmitter testAi2(@RequestParam("question") String question, HttpServletRequest request) {
        // 创建 SseEmitter 对象，用于流式推送
        SseEmitter emitter = new SseEmitter();
        System.out.println("请求进来了，对应的问题是: " + question);

        String ip = getClientIp(request);
        try {
            QueryWrapper<RequestLog> wrapper = new QueryWrapper<>();
            // 获取今天的开始和结束时间
            LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
            LocalDateTime endOfDay = LocalDate.now().atTime(23, 59, 59, 999999999);

            // 添加时间范围查询条件
            wrapper.between("request_time", startOfDay, endOfDay);
            wrapper.eq("ip",ip);
            Long count = requestLogMapper.selectCount(wrapper);
            if(20 < count){
                throw new Exception("访问次数已达今日上线，请稍后再试 ");
            }
            RequestLog requestLog = new RequestLog();
            requestLog.setRequestTime(LocalDateTime.now());
            requestLog.setIp(ip);
            requestLog.setParams(question);
            requestLogMapper.insert(requestLog);
        } catch (RuntimeException e) {
            System.out.println("数据记录异常："+e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e + ip);
        }

        // 创建新的线程来处理流式数据
        new Thread(() -> {
            try {
                // 获取流式数据
                List<ChatMessage> messages = new ArrayList<>();
                ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), question);
                messages.add(chatMessage);
                String requestId = UUID.randomUUID().toString();
                ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
                        .model(Constants.ModelChatGLM4)
                        .stream(Boolean.TRUE)
                        .messages(messages)
                        .requestId(requestId)
                        .build();

                ModelApiResponse sseModelApiResp = client.invokeModelApi(chatCompletionRequest);

                if (sseModelApiResp.isSuccess()) {
                    AtomicBoolean isFirst = new AtomicBoolean(true);

                    // 将流数据映射到累加器并推送到前端
                    mapStreamToAccumulator(sseModelApiResp.getFlowable(), chatMessage)
                            .doOnNext(accumulator -> {

                                if (accumulator.getDelta() != null && accumulator.getDelta().getContent() != null) {
                                    // 通过 SSE 推送数据到前端
                                    try {
                                        emitter.send(accumulator.getDelta().getContent(), MediaType.TEXT_PLAIN);
                                    } catch (IOException e) {
                                        System.err.println("发送数据失败: " + e.getMessage());
                                        emitter.completeWithError(e);  // 发生错误时，关闭连接
                                    }
                                }
                            })
                            .doOnComplete(() -> {
                                try {
                                    // 在流完成时，发送 'end' 事件
                                    emitter.send(" ", MediaType.TEXT_PLAIN); // 发送 'end' 标志
                                    emitter.complete(); // 完成 SSE 流
                                } catch (IOException e) {
                                    System.err.println("完成流时发送数据失败: " + e.getMessage());
                                    emitter.completeWithError(e);  // 发生错误时，关闭连接
                                }
                            })
                            .blockingLast();
                }
            } catch (Exception e) {
                System.err.println("处理过程中发生错误: " + e.getMessage());
                emitter.completeWithError(e);
            }
        }).start();

        return emitter;
    }



    private static Flowable<ChatMessageAccumulator> mapStreamToAccumulator(Flowable<ModelData> flowable, ChatMessage chatMessage) {
        return flowable
                .map(modelData -> {
                    // 提取 ModelData 中的必要属性
                    Delta delta = modelData.getChoices().get(0).getDelta();
                    Choice choice = modelData.getChoices().get(0);
                    Usage usage = modelData.getUsage();
                    String id = modelData.getId();
                    long created = modelData.getCreated();

                    // 使用带参数的构造函数创建 ChatMessageAccumulator 对象
                    ChatMessageAccumulator accumulator = new ChatMessageAccumulator(delta, chatMessage, choice, usage, created, id);
                    return accumulator;
                });
    }

    public String getClientIp(HttpServletRequest request) {
        String clientIp = request.getHeader("X-Forwarded-For");
        if (clientIp == null || clientIp.isEmpty()) {
            // 如果没有代理转发，使用 RemoteAddr 获取 IP
            clientIp = request.getRemoteAddr();
        } else {
            // 如果有代理，X-Forwarded-For 会包含多个 IP，取第一个是客户端的真实 IP
            clientIp = clientIp.split(",")[0];
        }
        return clientIp;
    }

    @Autowired
    private ApplicationContext applicationContext;

    @PostMapping
    public String test(){
        TestServiceController bean = applicationContext.getBean(TestServiceController.class);
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        threadPool.execute(()->{
            try {
                bean.handleRequest();
            } catch (Exception e) {
                RequestLog requestLog = new RequestLog();
                requestLog.setRequestTime(LocalDateTime.now());
                requestLog.setIp("3.3.3.3");
                requestLog.setParams("3333");
                requestLogMapper.insert(requestLog);
                throw new RuntimeException(e);
            }
        });
        System.out.println("okkkkk");
        return "ok";
    }

    @Transactional(rollbackFor = Exception.class)
    public void handleRequest(){
        try {
            RequestLog requestLog = new RequestLog();
            requestLog.setRequestTime(LocalDateTime.now());
            requestLog.setIp("1.1.1.1");
            requestLog.setParams("testtesttest");
            requestLogMapper.insert(requestLog);
            throw new Exception("触发异常");
        } catch (Exception e) {
            RequestLog requestLog = new RequestLog();
            requestLog.setRequestTime(LocalDateTime.now());
            requestLog.setIp("2.2.2.2");
            requestLog.setParams("2222");
            requestLogMapper.insert(requestLog);
            throw new RuntimeException(e);
        }
    }

}
